import math
import numpy
from scipy.interpolate import LinearNDInterpolator
from scipy.interpolate import interp1d
from ..dataclass.geoProfiles import Profile1D, MaterialTable
from ..dataclass.terminologies import GeoMaterialProps

from typing import Any, Optional, List, Dict, Tuple, Set, Union

footing: Any
d: Any
profile: Any
es: Any
p0: Any
result: Any

def cal_gama_m(profile: Profile1D, material_table: MaterialTable, use_effective_weight: bool = False, water_unit_wight: float = 9.8) -> float:
    """
    Calculate the weighted average weight of soil weight of a profile.
    For soil under groundwater table, saturated unit weight will be used.
    
    Parameters
    ----------
    profile: Profile1D
        The profile for calculation.
    
    material_table: MaterialTable
        The material table should have columns - MaterialProp.UnitWeight and MaterialProp.SaturateUnitWeight
    
    use_effective_weight: bool
        If it's True, the soil below water table will use effective unit weight instead of saturated unit weight.
        effective_unit_weight = saturated_unit_weight - water_unit_wight
    
    water_unit_wight: float
        It's used only when use_effective_weight is True.
    """
    ...

class RecFoundationSettle:
    """Calculate the settlement of a rectangular foundation."""
    def __init__(self, width: Any = None, length: Any = None, ground_elev: Any = None, bottom_depth: Any = None) -> Any:
        """
        Initialize RecFoundationSettle object.
        
        Parameters
        ----------
        width: (m) float
            The length of the foundation.
        
        length: (m) float
            The width of the foundation.
        
        ground_elev: (m) float
            The elevation of the design ground.
        
        bottom_depth: (m) float
            The depth of the foundation bottom from the ground elevation.
        """
        ...
    def additional_alpha(self, depth: float, average = True) -> float:
        """
        Calculate additional stress factor and average additional stress factor at the
        center under a rectangular uniform load.
        
        Parameters
        ----------
        depth (m): float, default: None
            The depth of the calculation point from the bottom of the foundation (rectangle).
        
        average: bool, default: True
            When it's true, the average additional stress alpha will be returned.
        """
        ...
    def layer_settle(self, top: float, bottom: float, es_i: float, p0: Any = None) -> float:
        """
        Calculate the settlement of 1 layer under the center of the foundation.
        
        Parameters
        ----------
        top (m): float
            The depth of the top of the layer from the bottom of the foundation.
        
        bottom (m): float
            The depth of the bottom of the layer from the bottom of the foundation.
        
        es_i (MPa): float
            The compression modulus of this layer.
        
        p0 (kPa): float | None, default: None
            The additional stress at the bottom of the foundation.
            If p0 is None, then A_i will be returned.
        """
        ...
    def total_settle(self, profile: list[float], es: list[float], p0: float, delta_z: float = 1, cal_depth: bool = True) -> dict[str, Any]:
        """
        Calculate the total settlement under the center of the foundation.
        
        Parameters
        ----------
        profile: (m) list[float]
            The bottom depth of each layer from the bottom of the foundation, including the top of the 1st layer.
            The first value of the profile is always 0 which is the depth of the bottom of the foundation.
            Example: [0, 1, 2,4, 5]
        
        es: (MPa) list[float]
            The compression modulus of each layer. Example: [2, 2.7, 4]
        
        p0: (kPa) float
            The additional stress at the bottom of the foundation.
        
        delta_z: (m) float, default: 1
            Used to decide the settlement calculation depth. It's not used when cal_depth is False.
        
        cal_depth: bool, default: True
            When it's True, settlement calculation depth is considered,
            or all the settlement of layers in the profile will be calculated.
        
        Returns
        -------
        dict[str, float | int]: {"settlement": float, "id": int, "is_depth_enough": bool, "settle_cal_depth": float,
        "spec_settlement": float}
        
        settlement (mm): the total settlement within the settlement calculation depth. If the settlement calculation
        depth is bigger than profile depth, the total settlement only considers the depth of the profile.
        
        bottom_layer_id: the id of the bottom layer within calculation depth, the id of 1st layer is 0.
        
        is_depth_enough: when it's True, the settlement calculation depth is smaller than profile depth.
        If the settlement calculation depth is not considered, it's always True.
        
        settle_cal_depth (m): the settlement calculation depth.
        
        infer_settlement (mm): when settlement calculation depth is not satisfied within the profile, the settlement
        will be calculated until it's satisfied which means we consider the last layer has infinite thickness.
        If the settlement calculation depth is smaller than profile depth, infer_settlement is equal to settlement.
        """
        ...
    def cal_equivalent_E(self, profile: list[float], es: list[float]) -> float:
        """
        Calculate the equivalent value of compression modulus E.
        
        Parameters
        ----------
        profile: (m) list[float]
            The bottom depth of each layer from the bottom of the foundation, including the top of the 1st layer.
            The first value of the profile is always 0 which is the depth of the bottom of the foundation.
            Example: [0, 1, 2,4, 5]
        
        es: (MPa) list[float]
            The compression modulus of each layer. Example: [2, 2.7, 4]
            Its length cannot be smaller than the len(profile) - 1
        
        Note
        ----
        The settlement calculation depth is not checked.
        The settlement calculation depth is always the depth of the profile.
        """
        ...
    def settle_empirical_psi(self, profile: list[float], es: list[float], fak: float, p0: float) -> float:
        """
        Calculate the settlement empirical coefficient.
        
        Parameters
        ----------
        profile: (m) list[float]
            The bottom depth of each layer from the bottom of the foundation, including the top of the 1st layer.
            The first value of the profile is always 0 which is the depth of the bottom of the foundation.
            Example: [0, 1, 2,4, 5]
        
        es: (MPa) list[float]
            The compression modulus of each layer. Example: [2, 2.7, 4]
        
        fak: (kPa) float
            The characteristic value of soil bearing capacity.
            Use the fak of the layer in which the foundation bottom is located.
        
        p0: (kPa) float
            The additional stress at the bottom of the foundation.
        
        Note
        ----
        The settlement calculation depth is not checked.
        The settlement calculation depth is always the depth of the profile.
        """
        ...

class CompositeRectFoundation(RecFoundationSettle):
    def settle_empirical_psi(self, profile: list[float], es: list[float]) -> float:
        """
        Calculate the settlement empirical coefficient of a composite foundation.
        
        Parameters
        ----------
        profile: (m) list[float]
            The bottom depth of each layer from the bottom of the foundation, including the top of the 1st layer.
            The first value of the profile is always 0 which is the depth of the bottom of the foundation.
            Example: [0, 1, 2,4, 5]
        
        es: (MPa) list[float]
            The compression modulus of each layer. Example: [2, 2.7, 4]
        
        Note
        ----
        The settlement calculation depth is not checked.
        The settlement calculation depth is always the depth of the profile.
        """
        ...
